/* 
 *  Copyright (c) 2011—2013 Panguso.com. All rights reserved. 
 *  File Name:  XESRandomReader.java                                      
 *  File Contents Outline :  XES随机读取器
 *  File  Create Date:   2012年7月30日
 *  File Version#: Revision#: #1                  
 *  File  Latest Modify Date : 2013年1月16日
 *  File Author :  bachuan@panguso.com
 */
package cn.edu.thu.log.xes;
import java.io.*;
import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;


import org.deckfour.xes.factory.XFactory;
import org.deckfour.xes.factory.XFactoryRegistry;
import org.deckfour.xes.in.XParser;
import org.deckfour.xes.in.XParserRegistry;
import org.deckfour.xes.model.XLog;
import cn.edu.thu.log.web.service.PropertiesReaderServices;
import cn.edu.thu.log.web.service.impl.PropertiesReaderServicesImpl;

import org.jdom.JDOMException;
import org.w3c.dom.Document;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import storage.dbhelper.XESHelper;
import storage.dbobject.DbXES;

public class XESRandomReader implements XESReaderInterface {

    DbXES currentXES;
    List<DbXES> currentXESList;
    int currentIndexInCurrentList;
    String sourchPath;
    String name;
    XLog log;
    //int size;
    int currentIndex;
    //branch_UUID or branch
    String currentBranch;
    //list of branch
    List<String> branchList;
    XESHelper xesh;
    List<DbXES> xesList;
    //for random
    double proportion;
    ArrayList<Float> proportionList;
    int totalBranchNum;
    int branchNum;
    int resultBranchNum;
    ArrayList<Integer> alreadyChosenList;
    List<String> chosenBranchList;

    public XESRandomReader() {
   //     System.out.println("XESRandomReader()");
        XFactory factory = XFactoryRegistry.instance().currentDefault();
        log = factory.createLog();
        //  size = 0;
        currentIndex = 0;
        currentIndexInCurrentList = -1;
        xesh = new XESHelper();

//for random
        proportion = 0.1;
        proportionList = new ArrayList<Float>();
        alreadyChosenList = new ArrayList<Integer>();

    }

    @Override
    public void setUpXESPara(String name) {
        this.name = name;
        branchList = new LinkedList();
        currentXESList = new LinkedList();
        alreadyChosenList = new ArrayList<Integer>();
        branchList = xesh.getBranchListByName(DbXES.cl_name, name, DbXES.cl_branch);
        currentBranch = branchList.get(currentIndex);
        currentXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, currentBranch);//currentIndex already the next index
//        currentXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, String.valueOf(currentIndex));//currentIndex already the next index
        // for random
        proportionList = new ArrayList<Float>();
        chosenBranchList = new LinkedList();
        totalBranchNum = branchList.size();
        for (float i = 1; i <= totalBranchNum; i++) {
            proportionList.add((i / new Float(totalBranchNum)));
        }
 //       System.out.println("totalBranchNum:" + totalBranchNum);
 //       System.out.println("proportionList:" + proportionList);
    }

    @Override
	public ArrayList<Float> gerRandomList() {
        // System.out.println("proportion:" + proportionList);
        return proportionList;
    }

    @Override
	public void setUpRandomProportion(double proportion) {
        proportion = proportion;
 //       System.out.println("proportion:" + proportion);

        resultBranchNum = (int) (proportion * totalBranchNum);
        //  System.out.println("resultBranchNum:" + resultBranchNum);
        currentIndex = 0;
        if (resultBranchNum == 0) {
            System.out.println("resultBranchNum=0:" + totalBranchNum);
            resultBranchNum = 1;
        }
 //       System.out.println("resultBranchNum:" + resultBranchNum);
        generateRandomList();
        System.out.println("alreadyChosenList:" + alreadyChosenList);
//        getFilesize();
//        System.out.print("\nthere are xes files:" + size);
    }

    private void generateRandomList() {
        while (alreadyChosenList.size() < resultBranchNum) {
            int randomBranch = (int) (Math.random() * resultBranchNum);
            if (!alreadyChosenList.contains(randomBranch)) {
                chosenBranchList.add(branchList.get(randomBranch));
                alreadyChosenList.add(randomBranch);
            }
        }
    }

    @Override
    public boolean hadNext() {
        currentIndexInCurrentList++;
        if (currentIndexInCurrentList < currentXESList.size()) {//still have more log in same name 
            currentXES = currentXESList.get(currentIndexInCurrentList);
            return true;
        } else {//currentList is finished,need to move on to next Index
            currentIndex++;
            if (currentIndex < chosenBranchList.size()) {//still have more branch in chosenBranchList
                currentBranch = chosenBranchList.get(currentIndex);//718
                while (currentBranch == null) {
                    currentIndex++;
                    currentBranch = chosenBranchList.get(currentIndex);//718
                }
                currentXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, currentBranch);//718
//            currentXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, String.valueOf(currentIndex));//currentIndex already the next index

                if (currentXESList == null || currentXESList.size() == 0) {
                    currentIndex = -1;//add
                    currentIndexInCurrentList = -1;//add
                    currentXES = null;
                    return false;
                }//finished read!
                else {
                    currentIndexInCurrentList = 0;
                    currentXES = currentXESList.get(currentIndexInCurrentList);
                    return true;
                }
            } else {//do not have more branch in chosenBranchList,this is last branch
                currentIndex = -1;//add
                currentIndexInCurrentList = -1;//add
                currentXES = null;
                currentXESList = new LinkedList();
                return false;
            }//finished read!
        }
    }

    @Override
    public XLog Next() throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException, JDOMException {
//        List<DbXES> list = xesh.getXESs(DbXES.cl_name, name);
        DbXES xes = currentXES;

        if (xes != null) {
            System.out.println("read log Next:currentXES:Name():" + currentXES.getName() + " Branch:" + currentXES.getBranch() + " currentIndex:" + currentIndex + " currentIndexInCurrentList:" + currentIndexInCurrentList);
            //change xmlString to Document
            String xmlString = xes.getXES();
            StringReader sr = new StringReader(xmlString);
            InputSource is = new InputSource(sr);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(is);

            PropertiesReaderServices x1 = PropertiesReaderServicesImpl.instance();
            //change Document to .xes File
            File tempFile = new File(x1.getProperties("XES_TEMPFILE_PATH") +UUID.randomUUID()+".xes");
            TransformerFactory tfactory = TransformerFactory.newInstance();
            Transformer transformer = tfactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(tempFile);
            transformer.transform(source, result);

            //read .XES file to XLog
            readOneXESToLog(tempFile);
            tempFile.delete();

        } else {
            // System.out.println("\ndidnot find xes:"+name+" currentIndex:"+currentIndex+" currentIndexInCurrentList:"+currentIndexInCurrentList);
        }
        return log;
    }

    @Override
    public DbXES NextXES() throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException, JDOMException {
//        List<DbXES> list = xesh.getXESs(DbXES.cl_name, name);
        DbXES xes = currentXES;
        if (xes != null) {
 //           System.out.println("read log Next:currentXES:Name():" + currentXES.getName() + " Branch:" + currentXES.getBranch() + " currentIndex:" + currentIndex + " currentIndexInCurrentList:" + currentIndexInCurrentList);
        }
        return xes;
    }

    /**
     * read logs in standard format file
     *
     * @param standardLogFile the absolute path of xes file
     * @return collections of XLog
     */
    private void readOneXESToLog(File sourceFile) {
        XFactory factory = XFactoryRegistry.instance().currentDefault();
        log = factory.createLog();
        // load source file
        Collection<XLog> logs = null;
        try {
            for (XParser parser : XParserRegistry.instance().getAvailable()) {
                if (parser.canParse(sourceFile)) {
                    // System.out.println("Using input parser: " + parser.name());
                    logs = parser.parse(sourceFile);

                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (XLog eachLog : logs) {
            log.addAll(eachLog);

        }
//        currentIndex++;

    }
}